<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="XqpD5" id="XqpD5"><span data-lake-id="uee99d63b" id="uee99d63b">典型回答</span></h1>
  <p data-lake-id="u152f5a78" id="u152f5a78"><br></p>
  <p data-lake-id="u52c49fa5" id="u52c49fa5"><span data-lake-id="u17c335d6" id="u17c335d6">锁是MySQL中并发控制的重要手段，InnoDB作为一种最常用的执行引擎，他支持很多种锁的类型。InnoDB中的锁根据不同的分类方式也有很多种分法。主要由以下这些：</span></p>
  <p data-lake-id="u779480fc" id="u779480fc"><span data-lake-id="u33f0ddfd" id="u33f0ddfd">​</span><br></p>
  <p data-lake-id="uc628d967" id="uc628d967"><span data-lake-id="u31ed51cb" id="u31ed51cb">按</span><strong><span data-lake-id="u5cfd98a3" id="u5cfd98a3">操作</span></strong><span data-lake-id="uc725e254" id="uc725e254">划分，可分为DML锁、DDL锁</span></p>
  <p data-lake-id="u8a2daf63" id="u8a2daf63"><span data-lake-id="u1ce149c8" id="u1ce149c8">按</span><strong><span data-lake-id="uc8cdee3f" id="uc8cdee3f">锁的粒度</span></strong><span data-lake-id="ucdde0d6b" id="ucdde0d6b">划分，可分为表级锁、行级锁、页级锁</span></p>
  <p data-lake-id="ue1980f0b" id="ue1980f0b"><span data-lake-id="uc3e08de8" id="uc3e08de8">按</span><strong><span data-lake-id="u4fdf05f5" id="u4fdf05f5">锁的级别</span></strong><span data-lake-id="u3c4efa5c" id="u3c4efa5c">划分，可分为共享锁、排他锁 详见</span></p>
  <p data-lake-id="u87427cbb" id="u87427cbb"><span data-lake-id="ua03dd0d9" id="ua03dd0d9">​</span><br></p>
  <p data-lake-id="u6f1699be" id="u6f1699be"><span data-lake-id="u62b12d8e" id="u62b12d8e">按</span><strong><span data-lake-id="u4ed023ce" id="u4ed023ce">加锁方式</span></strong><span data-lake-id="ub3ae8ee9" id="ub3ae8ee9">划分，可分为自动锁、显示锁</span></p>
  <p data-lake-id="u3fc54df4" id="u3fc54df4"><span data-lake-id="ufc88bc70" id="ufc88bc70">按</span><strong><span data-lake-id="uaea54201" id="uaea54201">使用方式</span></strong><span data-lake-id="u0b6e1cff" id="u0b6e1cff">划分，可分为乐观锁、悲观锁 详见 </span></p>
  <p data-lake-id="ua2f2777b" id="ua2f2777b"><span data-lake-id="u8ef75f1c" id="u8ef75f1c">​</span><br></p>
  <p data-lake-id="ubdb26c4f" id="ubdb26c4f"><span data-lake-id="uaffeae53" id="uaffeae53">按</span><strong><span data-lake-id="u3c2752d7" id="u3c2752d7">锁的对象</span></strong><span data-lake-id="ua23baa75" id="ua23baa75">划分，可分为记录锁、间隙锁、临键锁 详见</span></p>
  <p data-lake-id="u9b5aa048" id="u9b5aa048"><span data-lake-id="ubdf75087" id="ubdf75087">​</span><br></p>
  <p data-lake-id="u8f90b03f" id="u8f90b03f"><span data-lake-id="u85e2db23" id="u85e2db23">​</span><br></p>
  <h1 data-lake-id="R21Pm" id="R21Pm"><span data-lake-id="u4c676755" id="u4c676755">扩展知识</span></h1>
  <p data-lake-id="u7d700b78" id="u7d700b78"><br></p>
  <h2 data-lake-id="gaZ1M" id="gaZ1M"><span data-lake-id="u2097fc55" id="u2097fc55">字典锁</span></h2>
  <p data-lake-id="uf65a9e38" id="uf65a9e38"><br></p>
  <h2 data-lake-id="ioNFr" id="ioNFr"><span data-lake-id="u17c31b7e" id="u17c31b7e">意向锁</span></h2>
  <p data-lake-id="ucbbcbd06" id="ucbbcbd06"><br></p>
  <p data-lake-id="u14425070" id="u14425070"><br></p>
  <h2 data-lake-id="tE0sx" id="tE0sx"><span data-lake-id="u54a1b237" id="u54a1b237">行级锁、表级锁、页</span></h2>
  <p data-lake-id="u76c4b15f" id="u76c4b15f"><br></p>
  <h2 data-lake-id="B2P7z" id="B2P7z"><span data-lake-id="u2faf1e73" id="u2faf1e73">行级锁、表级锁、页级锁</span></h2>
  <p data-lake-id="ube386442" id="ube386442"><br></p>
  <h3 data-lake-id="gdz1R" id="gdz1R"><span data-lake-id="ua9fa17dc" id="ua9fa17dc">行级锁</span></h3>
  <p data-lake-id="u14c987f6" id="u14c987f6"><span data-lake-id="ub8189eba" id="ub8189eba">行级锁是Mysql中锁定粒度最细的一种锁，表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小，但加锁的开销也最大。行级锁分为</span><span data-lake-id="u83650e5b" id="u83650e5b">共享锁</span><span data-lake-id="ubd58031c" id="ubd58031c"> </span><span data-lake-id="u240fe6aa" id="u240fe6aa">和</span><span data-lake-id="uea276220" id="uea276220"> </span><span data-lake-id="u7feece54" id="u7feece54">排他锁</span><span data-lake-id="u2067bfd9" id="u2067bfd9">。</span></p>
  <p data-lake-id="udb001f99" id="udb001f99"><br></p>
  <p data-lake-id="u2d0580dd" id="u2d0580dd"><span data-lake-id="u68259b8d" id="u68259b8d">他的特点是开销大，加锁慢；会出现死锁；优点是锁定粒度最小，发生锁冲突的概率最低，并发度也最高。</span></p>
  <p data-lake-id="u1cd34d3a" id="u1cd34d3a"><span data-lake-id="uf946f0ef" id="uf946f0ef">​</span><br></p>
  <h3 data-lake-id="kJLSC" id="kJLSC"><span data-lake-id="u477e6ab0" id="u477e6ab0">表级锁</span></h3>
  <p data-lake-id="ub9039220" id="ub9039220"><span data-lake-id="uf744b085" id="uf744b085">表</span><span data-lake-id="u67b0d5fa" id="u67b0d5fa">级锁是MySQL中锁定粒度最大的一种锁，表示对当前操作的整张表加锁，它实现简单，资源消耗较少，被大部分MySQL引擎支持。最常使用的MYISAM与INNODB都支持表级锁定。</span></p>
  <p data-lake-id="ub6076319" id="ub6076319"><br></p>
  <p data-lake-id="u6df7c2ae" id="u6df7c2ae"><span data-lake-id="ue77b2c4c" id="ue77b2c4c">他的优点是开销小，加锁快；不会出现死锁；缺点是锁定粒度大，发出锁冲突的概率最高，并发度最低。</span></p>
  <p data-lake-id="u04d9fa25" id="u04d9fa25"><span data-lake-id="u16bf0d7b" id="u16bf0d7b">​</span><br></p>
  <h3 data-lake-id="A56TK" id="A56TK"><span data-lake-id="u4fb7ffce" id="u4fb7ffce">页级锁</span></h3>
  <p data-lake-id="ud86a7b66" id="ud86a7b66"><span data-lake-id="u967fb5f4" id="u967fb5f4">页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快，但冲突多，行级冲突少，但速度慢。所以取了折衷的页级，一次锁定相邻的一组记录。BDB支持页级锁</span></p>
  <p data-lake-id="u0a54ea04" id="u0a54ea04"><br></p>
  <p data-lake-id="u3207f198" id="u3207f198"><span data-lake-id="u7f5149d2" id="u7f5149d2">他的特点是开销和加锁时间界于表锁和行锁之间；会出现死锁；锁定粒度界于表锁和行锁之间，并发度一般</span></p>
  <p data-lake-id="u68de8e9d" id="u68de8e9d"><span data-lake-id="ubc4f7382" id="ubc4f7382">​</span><br></p>
  <h3 data-lake-id="tPlyb" id="tPlyb"><span data-lake-id="u529d837e" id="u529d837e">InnoDB中的行锁与表锁</span></h3>
  <p data-lake-id="uad3239de" id="uad3239de"><span data-lake-id="u30ff32af" id="u30ff32af"><br></span><span data-lake-id="uded71f7e" id="uded71f7e">InnoDB行锁是通过给索引上的索引项加锁来实现的，这一点MySQL与Oracle不同，后者是通过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味着：只有通过索引条件检索数据，InnoDB才使用行级锁，否则，InnoDB将使用表锁！</span></p>
  <p data-lake-id="u80208df1" id="u80208df1"><span data-lake-id="u3d459501" id="u3d459501">​</span><br></p>
  <p data-lake-id="u168aa187" id="u168aa187"><span data-lake-id="u7e767c9d" id="u7e767c9d">在实际应用中，要特别注意InnoDB行锁的这一特性，不然的话，可能导致大量的锁冲突，从而影响并发性能。</span></p>
  <ul list="uf8ca5619">
   <li fid="u56b55047" data-lake-id="u873724f0" id="u873724f0"><span data-lake-id="u2faf4212" id="u2faf4212">在不通过索引条件查询的时候,InnoDB 确实使用的是表锁,而不是行锁。</span></li>
   <li fid="u56b55047" data-lake-id="udf807b38" id="udf807b38"><span data-lake-id="u70dc3f15" id="u70dc3f15">由于 MySQL 的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行 的记录,但是如果是使用相同的索引键,是会出现锁冲突的。应用设计的时候要注意这一点。（参考：</span><a href="https://www.yuque.com/hollis666/vhr2ge/yywypm" data-lake-id="ua9785c80" id="ua9785c80"><span data-lake-id="u0955278a" id="u0955278a">https://www.yuque.com/hollis666/vhr2ge/yywypm</span></a><span data-lake-id="ud2096aef" id="ud2096aef"> ）</span></li>
   <li fid="u56b55047" data-lake-id="uc72937ac" id="uc72937ac"><span data-lake-id="ufec489a3" id="ufec489a3">当表有多个索引的时候,不同的事务可以使用不同的索引锁定不同的行,另外,不论 是使用主键索引、唯一索引或普通索引,InnoDB 都会使用行锁来对数据加锁。</span></li>
   <li fid="u56b55047" data-lake-id="u4b4c0359" id="u4b4c0359"><span data-lake-id="u04544bc4" id="u04544bc4">即便在条件中使用了索引字段,但是否使用索引来检索数据是由 MySQL 通过判断不同 执行计划的代价来决定的,如果 MySQL 认为全表扫 效率更高,比如对一些很小的表,它 就不会使用索引,这种情况下 InnoDB 将使用表锁,而不是行锁。因此,在分析锁冲突时, 别忘了检查 SQL 的执行计划,以确认是否真正使用了索引。</span></li>
  </ul>
 </body>
</html>